package com.konsung.ksdc.common.mqtt.parser;

import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;

import com.ibm.mqtt.MqttException;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.QueryBuilder;
import com.konsung.ksdc.bean.MqttMsgBean;
import com.konsung.ksdc.bean.netbean.GroupNetBean;
import com.konsung.ksdc.common.database.DatabaseHelper;
import com.konsung.ksdc.common.utils.BroadCastActions;
import com.konsung.ksdc.common.utils.JsonUtils;
import com.konsung.ksdc.config.MyApplication;
import com.konsung.ksdc.config.NetConfig;
import com.konsung.ksdc.service.MqttService;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 消息转换器抽象类
 * Created by andy on 2017/4/19.
 */
public abstract class MqttMessageHandler {
    public static final String MSG_TARGET_TYPE_PERSONAL = "1";
    public static final String MSG_TARGET_TYPE_GROUP = "2";

    public static final String MSG_TYPE_TXT = "1"; // 文本消息
    public static final String MSG_TYPE_VOICE = "2"; // 语音消息
    public static final String MSG_TYPE_PIC = "3"; // 图片消息
    public static final String MSG_TYPE_REQUEST_PASSED = "4"; // 好友验证通过消息
    public static final String MSG_TYPE_REQUEST_RECEIVED = "5"; // 好友申请消息
    public static final String MSG_TYPE_DELETE_CONTACT = "6"; // 删除好友消息
    public static final String MSG_TYPE_WIKI = "7"; // 百科消息
    public static final String MSG_TYPE_REQUEST_GROUP = "8"; // 申请群消息
    public static final String MSG_TYPE_DELETE_GROUP = "9"; // 移除群成员消息
    public static final int MSG_TYPE_START = 0;
    public static final int MSG_TARGET_TYPE_START = 1;
    public static final int MSG_SEND_DATE_START = 2;
    public static final int MSG_USER_ID_START = 16;
    public static final int MSG_CONTENT_START = 48;
    public static final int MSG_VOICE_CONTENT_START = 53;
    private static final int MSG_DELAY = 54;
//    private Handler handler = new Handler() {
//        public void handleMessage(Message msg) {
//            switch (msg.what) {
//                case MSG_DELAY:
//                    LogUtils.e("handler", "延时sendBroadcast :更新广播或者添加成员广播");
//                    sendMsg(mqttMsgBean, action);
//                    break;
//            }
//            super.handleMessage(msg);
//        }
//    };

    /**
     * 消息对象转换成二进制数组，此方法一般用于客户端发送MQTT消息到服务器之前，进行的数据转换
     * @param mqttMsgBean 消息对象
     * @return 字节数组
     * @throws Exception 异常
     */
    public abstract byte[] parseMessage(MqttMsgBean mqttMsgBean) throws Exception;

    /**
     * 二进制数组转换成消息实体对象，此方法一般用于接收到服务端消息后，转换成实体对象，以便使用
     * @param topicName 消息主题
     * @param datas 数据包
     * @return 消息实体
     * @throws Exception 异常
     */
    public abstract MqttMsgBean parseMessage(String topicName, byte[] datas) throws Exception;

    /**
     * 写入消息提醒
     * 通过ID唯一区别消息提醒，如果本条消息为个人消息，
     * 则ID为好友的userId，反之则为群组的topicName
     * @param topicName 名字
     * @param isRead 是否已读
     * @param msg 消息
     * @throws Exception 异常
     */
    public abstract void writeNotice(String topicName, String isRead, MqttMsgBean msg)
            throws Exception;

    /**
     * 处理消息
     * @param topicName 消息主题
     * @param datas 数据包
     * @throws Exception 异常
     */
    public abstract void hanlderReceivedMessage(String topicName, byte[] datas) throws Exception;

    /**
     * 拼装消息头
     * @param mqttMsgBean 消息实体对象
     * @return 拼接后的消息头
     */
    protected String getMessageHeader(MqttMsgBean mqttMsgBean) {
        return mqttMsgBean.getMsgType() + mqttMsgBean.getMsgTargetType()
                + mqttMsgBean.getMsgSendDate() + mqttMsgBean.getContact();
    }

    /**
     * 将MQTT二进制消息转换成消息对象
     * content[0] 储存消息类型，字符串值1=文字 2=语音 3=图片
     * content[1] 储存消息目标类型：1=个人，2=群体
     * content[2-15] 储存消息发生日期，如20160502131121
     * content[16-47] 存储联系人32位长度ID，如：c1d32eee008c4f2fbae2b27ff38911ad
     * content[48~+] 储存数据
     * @param topicName 名字
     * @param content 内容
     * @return 客户端数据
     */
    public MqttMsgBean fillMsgBeanHeader(String topicName, byte[] content) {

        // 消息类型
        String msgType = new String(Arrays.copyOf(content, MSG_TYPE_START + 1));

        // 消息目标类型
        String msgTargetType = new String(Arrays.copyOfRange(content,
                MSG_TARGET_TYPE_START, MSG_TARGET_TYPE_START + 1));

        // 消息发送日期
        String msgSendDate = new String(Arrays.copyOfRange(content,
                MSG_SEND_DATE_START, MSG_SEND_DATE_START + 14));

        // 消息发送者ID
        String userId = new String(Arrays.copyOfRange(content,
                MSG_USER_ID_START, MSG_USER_ID_START + 32));

        MqttMsgBean msg = new MqttMsgBean();
        msg.setContact(userId);
        msg.setMsgType(msgType);
        msg.setMsgTargetType(msgTargetType);
        msg.setMsgSendDate(msgSendDate);
        msg.setTopicName(topicName);
        msg.setOwnerUserId(NetConfig.currentUser.getUserId());
        return msg;
    }

    /**
     * 字节数组合并
     * @param arr1 字节
     * @param arr2 字节
     * @return 数组数据
     */
    public static byte[] byteArrayConcat(byte[] arr1, byte[] arr2) {
        byte[] result = new byte[arr1.length + arr2.length];
        System.arraycopy(arr1, 0, result, 0, arr1.length);
        System.arraycopy(arr2, 0, result, arr1.length, arr2.length);
        return result;
    }

    /**
     * 发送消息广播
     * @param msgBean 消息实体
     */
    public void sendBroadcast(MqttMsgBean msgBean) {
        String json = JsonUtils.toJson(msgBean);

        Intent intent = new Intent();
        intent.setAction(BroadCastActions.ACTION_MESSAGE_RECEIVED);
        intent.putExtra(BroadCastActions.EXTRA_MESSAGE, json);

        MyApplication.getContext().sendBroadcast(intent);
    }

    protected MqttMsgBean mqttMsgBean;
    protected String action;

    /**
     * Yn
     */
    public class SendTimerTask extends TimerTask {

        @Override
        public void run() {
            sendMsg(mqttMsgBean, action);
        }
    }

    private SendTimerTask task;
    private Timer timer = new Timer();

    /**
     * 发送消息广播
     * @param msgBean 消息实体
     * @param action 广播动作
     */
    public void sendBroadcast(MqttMsgBean msgBean, String action) {
        this.mqttMsgBean = msgBean;
        this.action = action;
        //离线发送移除在邀请，由于mqtt离线消息有缺陷，没有排序，在此延迟
        if (action.equals(BroadCastActions.ACTION_REQUEST_GROUP_RECEIVED)) {
            if (task != null) {
                task.cancel();  //将原任务从队列中移除
            }
            task = new SendTimerTask();
            timer.schedule(task, 500);
        } else {
            sendMsg(msgBean, action);
        }
    }

    /**
     * @param msgBean 消息实体
     * @param action 广播
     */

    private void sendMsg(MqttMsgBean msgBean, String action) {
        String json = JsonUtils.toJson(msgBean);
        Intent intent = new Intent();
        intent.setAction(action);
        intent.putExtra(BroadCastActions.EXTRA_MESSAGE, json);
        MyApplication.getContext().sendBroadcast(intent);
    }

    /**
     * 从意图中提取出mqtt消息对象
     * @param intent 意图
     * @return 消息实体对象
     */
    public static MqttMsgBean obtainMessage(Intent intent) {
        String json = intent.getStringExtra(BroadCastActions.EXTRA_MESSAGE);
        return JsonUtils.toEntity(json, MqttMsgBean.class);
    }

    /**
     * 播放提示音
     */
    public void playSound() {
        Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        Ringtone r = RingtoneManager.getRingtone(MyApplication.getContext(), notification);
        r.play();
    }

    /**
     * 检查群组是否存在
     * @param groupId 群组topic
     * @return 是否存在  false不会收到消息
     */
    public boolean isGroupExits(final String groupId) {
        Dao dao = null;
        try {
            dao = DatabaseHelper.getHelper(MyApplication.getContext()).
                    getDao(GroupNetBean.class);
            //根据唯一的groupId查询本地的群组数据
            QueryBuilder qb = dao.queryBuilder();
            qb.where().eq("groupId", groupId).and().eq("ownerId", NetConfig.
                    currentUser.getUserId());
            List<GroupNetBean> groups = dao.query(qb.prepare());
            if (groups != null && groups.size() > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // mqttClient重新连接，在子线程再次解绑
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (MqttService.mqttClient != null && MqttService.mqttClient.isConnected()) {
                    try {
                        MqttService.mqttClient.unsubscribe(new String[]{groupId});
                    } catch (MqttException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        return false;
    }
}
